#ifndef _PAGING_H_
#define _PAGING_H_

#define PGDIR_INDEX(x)	(x >> 22)
#define PGTAB_INDEX(x)	((x >> 12) & 0x3FF)

#define PAGE_FLAGS_PRESENT	(1 << 0)
#define PAGE_FLAGS_WRITE	(1 << 1)
#define PAGE_FLAGS_USER		(1 << 2)
#define PAGE_FLAGS_WRTH		(1 << 3)
#define PAGE_FLAGS_NOCACHE	(1 << 4)
#define PAGE_FLAGS_ACCESSED	(1 << 5)
#define PAGE_FLAGS_DIRTY	(1 << 6)
#define PAGE_FLAGS_PGSIZE	(1 << 7)
#define PAGE_FLAGS_GLOBAL	(1 << 8)

struct Page {
	dword present	: 1;	// Page present in memory
	dword rw	: 1;	// Read-only if clear, readwrite if set
	dword user	: 1;	// Supervisor level only if clear
	dword accessed	: 1;	// Has the page been accessed since last refresh?
	dword dirty	: 1;	// Has the page been written to since last refresh?
	dword unused	: 7;	// Amalgamation of unused and reserved bits
	dword frame	: 20;	// Frame address (shifted right 12 bits)
};

struct PageTable {
	struct Page Pages[1024];
};

struct PageDirectory {
	struct PageTable *Tables[1024];
	dword TablesPhys[1024];
};

class Paging {
public:
	static void Init();
	static void MapMemory(word flags, dword virt, dword phys, dword size);
	static void MapPage(word flags, dword virt, dword phys);

private:
	static dword virt2phys(dword virt);
};

#endif
